package com.ldn.common.basic.utils.tencent;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ldn.common.basic.dispose.bo.WechatAppletUserBo;
import com.ldn.common.basic.utils.cache.CacheUtils;
import com.ldn.common.basic.utils.system.DateUtils;
import com.ldn.common.basic.utils.system.HttpUtils;
import com.ldn.common.basic.utils.system.StrUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * 微信常用操作工具类
 *
 * @author 李大牛家的牛 (scafel@163.com)
 * @product serverless
 * @className WechatUtils
 * @createDate 2025/2/6 - 15:26
 * @description 微信工具类
 **/
@Slf4j
public class WechatUtils {

    /**
     * 获取微信access token 方法
     * 用于获取access token并保存到缓存中实现全局唯一
     *
     * @author 李大牛家的牛 (scafel@163.com)
     * @param appid: 小程序或公众号的appid
     * @param secret: 小程序或公众号的secret
     * @return java.lang.String 获取到的access token
     **/
    public static String getAccessToken(String appid, String secret) throws RuntimeException {
        AccessToken token = CacheUtils.getObj("wechat_access_token_" + appid, AccessToken.class);
        log.info("微信获取token token => {}", token.toString());
        if (StrUtils.isBlank(token.getAccessToken()) || token.getExpiresIn() <= DateUtils.getCurrentS()) {
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
            String replaceUrl = url.replace("{0}", appid).replace("{1}", secret);
            String res = HttpUtils.get(replaceUrl);
            JSONObject jsonObject = JSONUtil.parseObj(res);
            log.info("微信获取token res => {}", jsonObject);
            String errcode = jsonObject.getStr("errcode");
            if (StrUtils.isBlank(errcode) || StrUtils.compare(errcode, "0", true) == 0){
                AccessToken accessToken = new AccessToken();
                accessToken.setAccessToken(jsonObject.getStr("access_token"));
                accessToken.setExpiresIn(jsonObject.getInt("expires_in") + DateUtils.getCurrentS());
                CacheUtils.set("wechat_access_token", accessToken);
                return accessToken.getAccessToken();
            }
            throw new RuntimeException(jsonObject.getStr("errmsg"));
        }
        return token.getAccessToken();
    }

    /**
     * 小程序获取用户手机号
     *
     * @author 李大牛家的牛 (scafel@163.com)
     * @param appId: 小程序appid
     * @param secret: 小程序secret
     * @param code: 登录凭证(有效期五分钟)
     * @return java.lang.String 微信用户手机号
     **/
    public static String getUserPhone(String appId, String secret, String code) throws RuntimeException {
        String accessToken = getAccessToken(appId, secret);
        if (StrUtils.isBlank(accessToken)){
            throw new RuntimeException("微信令牌获取失败!");
        }
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
        JSONObject params = JSONUtil.createObj();
        params.set("code", code);
        String res = HttpUtils.post(url, params.toString());
        JSONObject jsonObject = JSONUtil.parseObj(res);
        log.info("微信获取用户手机号 res => {}", jsonObject);
        String errcode = jsonObject.getStr("errcode");
        if (StrUtils.isBlank(errcode) || StrUtils.compare(errcode, "0", true) == 0){
            JSONObject phone_info = jsonObject.getJSONObject("phone_info");
            String phoneNumber = phone_info.getStr("phoneNumber");
            if (StrUtils.isBlank(phoneNumber)) {
                throw new RuntimeException("获取用户手机号失败!手机号为空");
            }
            return phoneNumber;
        }
        throw new RuntimeException(jsonObject.getStr("errmsg"));
    }
    /**
     * 小程序登录
     *
     * @author 李大牛家的牛 (scafel@163.com)
     * @param appid: 小程序appid
     * @param secret: 小程序secret
     * @param code: 登录凭证(有效期五分钟)
     * @return com.ldn.common.basic.dispose.bo.WechatAppletUserBo 微信小程序用户信息
     **/
    public static WechatAppletUserBo wechatAppletLogin(String appid, String secret, String code) {
        WechatAppletUserBo packet = new WechatAppletUserBo();
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
        String replaceUrl = url.replace("{0}", appid).replace("{1}", secret).replace("{2}", code);
        String res = HttpUtils.get(replaceUrl);
        JSONObject jsonObject = JSONUtil.parseObj(res);
        String errcode = jsonObject.getStr("errcode");
        if (StrUtils.isBlank(errcode)) {
            errcode = "0";
        }
        packet.setErrCode(errcode);
        if (StrUtils.compare(errcode, "0", true) == 0){
            packet.setSessionKey(jsonObject.getStr("session_key"));
            packet.setOpenId(jsonObject.getStr("openid"));
            packet.setUnionId(jsonObject.getStr("unionid"));
        }
        packet.setErrMsg(jsonObject.getStr("errmsg"));
        log.info("WechatAppletUserBo:{}", packet);
        return packet;
    }
    /**
     * 发送小程序订阅消息
     *
     * @author 李大牛家的牛 (scafel@163.com)
     * @param appid: 小程序appid
     * @param secret: 小程序secret
     * @param templateId: 订阅消息模板id
     * @param openId: 用户openid
     * @param data: 订阅消息内容
     **/
    public static void sendAppletSubscribeMessage(String appid, String secret, String templateId, String openId, String data) {
        String accessToken = getAccessToken(appid, secret);
        if (StrUtils.isBlank(accessToken)){
            throw new RuntimeException("微信令牌获取失败!");
        }
        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
        JSONObject params = JSONUtil.createObj();
        params.set("template_id", templateId);
        params.set("touser", openId);
        params.set("lang", "zh_CN");
        params.set("data", data);
        String res = HttpUtils.post(url, params.toString());
        JSONObject jsonObject = JSONUtil.parseObj(res);
        String errcode = jsonObject.getStr("errcode");
        if (StrUtils.isBlank(errcode)) {
            errcode = "0";
        }
        log.info("微信发送订阅消息 res => {}", jsonObject);
    }

}



/**
 * 微信access token
 *
 * @author 李大牛家的牛 (scafel@163.com)
 * @product serverless
 * @className AccessToken
 * @createDate 2025/2/6 - 15:26
 * @description 微信 access token
 **/
@Getter
@Setter
class AccessToken {
    /**
     * access token
     */
    private String accessToken;
    /**
     * 过期时间
     */
    private long expiresIn = 0;

    @Override
    public String toString() {
        return "AccessToken{'accessToken:'" + accessToken + ", expiresIn:" + expiresIn + '}';
    }
}
